<template>
  <div class="tag-admin">
    <div class="modules">
      <!-- 管理模块 -->
      <div>
        <el-button
          type="primary"
          icon="el-icon-plus"
          @click="moduleAdmin"
        >管理分组模块</el-button>
      </div>
      <div class="search-box">
        <el-select
          ref="search"
          :loading="loading"
          v-model="searchValue"
          filterable
          remote
          reserve-keyword
          placeholder="请输入关键词"
          :remote-method="remoteMethod"
          @change="selectHandle"
        >
          <el-option-group
            v-for="group in tagOpts"
            :label="group.mod_name"
            :key="group.mod_id"
          >
            <el-option
              v-for="item in group.options"
              :key="item.label_id"
              :label="item.label_name"
              :value="item.label_id"
            >
            </el-option>
          </el-option-group>
        </el-select>
        <el-button
          type="primary"
          @click="$refs.search.focus()"
        >搜搜</el-button>
      </div>
      <div class="module-list">
        <div
          class="module-list_item"
          v-for="it in moduleList"
          :key="it.mod_id"
          :class="{ active: activeGroup === it.mod_id }"
          @click="moduleClick(it)"
        >
          <span class="label">{{ it.mod_name }}</span>
          <span class="count">共{{ it.count_of_labels }}个内容标签</span>
        </div>
      </div>
    </div>
    <div
      class="tags"
      v-loading="loading2"
    >
      <div
        v-if="activeGroup"
        class="add-btn"
        @click="insertOne"
      >
        <i class="el-icon-plus"></i>
        <span>添加</span>
      </div>
      <el-tree
        ref="tree"
        :data="tagData"
        node-key="label_id"
        draggable
        :props="{ label: 'label_name' }"
        default-expand-all
        :expand-on-click-node="false"
        :allow-drop="allowDrop"
        @node-click="nodeClickHandle"
        @node-drop="nodeDropHandle"
      >
        <span
          class="custom-tree-node"
          slot-scope="{ node, data }"
        >
          <el-input
            ref="input"
            v-if="data.isEdit"
            v-model="data.label_name"
            @click.native.stop
            @blur="blurHandle(node, data, $event)"
          ></el-input>
          <div
            v-else
            class="tag-name"
            @dblclick="nodeDbclick(data)"
          >
            <span class="label">{{ node.label }}</span>
            <span class="count">关联{{ data.CountOfFbs }}条反馈</span>
            <span class="icons">
              <i
                class="el-icon-circle-plus-outline"
                @click.stop="append(node, data)"
              ></i>
              <i
                class="el-icon-delete"
                @click.stop="remove(node, data)"
              ></i>
            </span>
          </div>
        </span>
      </el-tree>
    </div>
    <div
      class="tag-detail"
      v-show="detailShow"
    >
      <div class="tag-name ellipsis">{{ tagDetail.label }}</div>
      <el-form
        label-suffix="："
        label-position="left"
      >
        <el-form-item label="创建时间">
          <span>{{ tagDetail.created_at | parseTime }}</span>
        </el-form-item>
        <el-form-item label="所属模块">
          <span>{{ getModuleName(tagDetail.mod_id) }}</span>
        </el-form-item>
        <el-form-item label="详细备注">
          <el-input
            v-model="tagDetail.note"
            type="textarea"
            :rows="3"
            placeholder="请输入备注信息"
            @blur="textareaBlur"
          >
          </el-input>
        </el-form-item>
      </el-form>
      <i
        class="el-icon-close"
        @click="detailShow = false"
      ></i>
    </div>
    <!--删除提示-->
    <el-dialog
      custom-class="tips-dialog"
      :visible.sync="dialog.show"
      title="提示"
      width="30%"
    >
      <el-form label-position="left">
        <el-form-item>
          {{ dialog.title }}
        </el-form-item>
        <el-form-item style="margin-left: 80px">
          <el-radio-group v-model="dialog.value">
            <el-radio :label="1">只删除标签</el-radio>
            <el-radio :label="2">删除此标签及相关反馈</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <span
        slot="footer"
        class="dialog-footer"
      >
        <el-button @click="cancelDel">取 消</el-button>
        <el-button
          type="primary"
          @click="saveDel"
        >删 除</el-button>
      </span>
    </el-dialog>
    <module-admin
      :visible.sync="moduleShow"
      :type="activeGroup"
      :projectId="projectId"
      @close="refresh"
    />
  </div>
</template>

<script type="text/javascript">
import Clickoutside from 'element-ui/lib/utils/clickoutside'
import ModuleAdmin from './ModuleAdmin.vue'
import { addTag, modifyTag, delTag } from '@/api/feedback/tagLib'
import { parseTime } from '@/utils/'
import { getModuleList, getTagList } from '../../resource'
export default {
  name: 'TagAdmin',
  components: { ModuleAdmin },
  directives: { Clickoutside },
  props: {
    projectId: [Number, String]
  },
  data () {
    return {
      loading: false,
      loading2: false,
      activeGroup: 0, // 激活模块
      activeId: '', // 激活标签
      searchValue: '',
      searchTags: [], // 搜索标签结果
      moduleList: [],
      tagData: [],
      tagDetail: {},
      detailShow: false,
      dialog: {
        show: false,
        title: '',
        value: 1
      },
      moduleShow: false
    }
  },
  created () {
    this.init()
  },
  methods: {
    async init () {
      this.moduleList = []
      this.tagData = []
      await this.getGroupList()
      if (this.moduleList.length) {
        this.activeGroup = this.moduleList[0].mod_id
        this.getList()
      }
    },
    async refresh (updated) {
      // 没有变化不刷新
      if (!updated) return
      await this.getGroupList()
      // 当前选中项被删除了
      if (this.moduleList.length) {
        if (this.moduleList.every(t => t.mod_id !== this.activeGroup)) {
          this.activeGroup = this.moduleList[0].mod_id
          this.getList()
        }
      } else {
        this.activeGroup = 0
        this.activeId = ''
        this.tagData = []
      }
    },
    // 组列表
    getGroupList () {
      return getModuleList({
        pro_id: this.projectId
      }).then(list => {
        this.moduleList = list
      })
    },
    // 成员列表
    getList (mod_id = this.activeGroup) {
      this.detailShow = false
      this.loading2 = true
      return this.getTags({
        mod_id
      }).then(list => {
        this.tagData = list.map(t => ({
          ...t,
          label: t.label_name,
          isEdit: false
        }))
        this.$nextTick(() => {
          this.activeId && this.$refs.tree.setCurrentKey(this.activeId)
        })
      }).finally(() => {
        this.loading2 = false
      })
    },
    getTags (params = {}, order = true) {
      return getTagList({
        pro_id: this.projectId,
        ...params
      }, order)
    },
    moduleClick ({ mod_id }) {
      this.activeGroup = mod_id
      this.getList()
    },
    insertOne () {
      this.tagData.unshift(this.createNewTag())
      this.inputFocus()
    },
    append (node, data) {
      const parent = node.parent
      const children = parent.data.children || parent.data
      const index = children.findIndex(t => t.label_id === data.label_id)
      const newChild = this.createNewTag(children[index].label_id)
      children.splice(index + 1, 0, newChild)
      this.inputFocus()
    },
    remove (node, data, revoke = false) {
      const parent = node.parent
      const children = parent.data.children || parent.data
      this.dialog = {
        show: true,
        title: `标签【${data.label}】关联${data.CountOfFbs}条反馈，是否要继续删除此标签？`,
        value: 1,
        parent: children,
        data,
        revoke
      }
    },
    cancelDel () {
      if (this.dialog.revoke) {
        this.dialog.data.label_name = this.dialog.data.label
      }
      this.dialog.show = false
    },
    saveDel () {
      delTag({
        label_id: this.dialog.data.label_id,
        del_data: this.dialog.value
      }).then(res => {
        if (res.code === 200) {
          const index = this.dialog.parent.findIndex(
            d => d.label_id === this.dialog.data.label_id
          )
          index !== -1 && this.dialog.parent.splice(index, 1)
          this.$message.success('删除成功！')
          this.dialog.show = false
          this.setModLabels()
          this.updateOrders()
        }
      })
    },
    async blurHandle (node, data, e) {
      const val = e.target.value.trim()
      const { label_id: labelId } = data
      if (!val) {
        const parent = node.parent
        const children = parent.data.children || parent.data
        // 删除已生成的数据
        if (labelId) {
          // this.remove(node, data, true)
          data.label_name = data.label
          data.isEdit = false
        } else {
          const index = children.findIndex(t => t.label_id === labelId)
          children.splice(index, 1)
        }
      } else {
        const isAdd = !labelId
        const api = isAdd ? addTag : modifyTag
        let params = { ...data }
        if (isAdd) {
          params.client_id = Date.now()
          params = [params]
        }
        api(params).then(res => {
          if (res.code === 200 && isAdd) {
            data.label_id = res.data[0].label_id
            data.created_at = parseTime(new Date())
            this.setModLabels()
            this.updateOrders()
          }
          data.label = data.label_name
          data.isEdit = false
        })
      }
    },
    nodeDropHandle (draggingNode) {
      const { label_id: labelId } = draggingNode.data
      const draggingIndex = this.tagData.findIndex(t => t.label_id === labelId)
      modifyTag({
        label_id: labelId,
        label_idx:
          draggingIndex === 0 ? 0 : this.tagData[draggingIndex - 1].label_id
      }).then(() => {
        this.updateOrders()
      })
    },
    nodeClickHandle (data, node, cmp) {
      this.tagDetail = data
      this.detailShow = true
    },
    nodeDbclick (data) {
      data.isEdit = true
      this.inputFocus()
    },
    textareaBlur () {
      modifyTag(this.tagDetail)
    },
    allowDrop (draggingNode, dropNode, type) {
      return type !== 'inner'
    },
    moduleAdmin () {
      this.moduleShow = true
    },
    setModLabels () {
      const moduleItem = this.moduleList.find(t => t.mod_id === this.activeGroup)
      moduleItem && (moduleItem.count_of_labels = this.tagData.length)
    },
    createNewTag (label_idx = 0, label_pid = 0) {
      return {
        isEdit: true,
        label_id: '',
        mod_id: this.activeGroup,
        label_name: '',
        label_idx,
        label_pid,
        label_status: 1,
        note: '',
        created_at: '',
        CountOfFbs: 0
      }
    },
    // 搜索出来后上颜色
    brightenKeyword (val) {
      val = val + ''
      const { searchValue } = this
      if (val.indexOf(searchValue) !== -1 && searchValue !== '') {
        return val.replace(
          searchValue,
          '<span class="mark" >' + searchValue + '</span>'
        )
      } else {
        return val
      }
    },
    inputFocus () {
      this.$nextTick(() => {
        this.$refs.input && this.$refs.input.focus()
      })
    },
    getModuleName (modId) {
      const it = this.moduleList.find(t => t.mod_id === modId)
      return it ? it.mod_name : ''
    },
    remoteMethod (query) {
      if (query) {
        this.loading = true
        this.getTags({
          param: query,
          mod_id: this.moduleList.map(t => t.mod_id).join(',')
        }, false)
          .then(list => {
            this.searchTags = list
          })
          .finally(() => {
            this.loading = false
          })
      } else {
        this.searchTags = []
      }
    },
    selectHandle (labelId) {
      const item = this.searchTags.find(t => t.label_id === labelId)
      this.activeGroup = item.mod_id
      this.activeId = item.label_id
      this.getList()
      this.tagDetail = item
      this.detailShow = true
    },
    updateOrders () {
      this.tagData.forEach((item, index, arr) => {
        const prevItem = arr[index - 1]
        item.label_idx = prevItem ? prevItem.label_id : 0
      })
    }
  },
  computed: {
    tagOpts () {
      const map = this.searchTags.reduce((map, it) => {
        if (!map[it.mod_id]) {
          map[it.mod_id] = [it]
        } else {
          map[it.mod_id].push(it)
        }
        return map
      }, {})
      return this.moduleList.reduce((arr, item) => {
        const options = map[item.mod_id]
        options && arr.push({
          mod_id: item.mod_id,
          mod_name: item.mod_name,
          mod_idx: item.mod_idx,
          options
        })
        return arr
      }, [])
    }
  }
}
</script>

<style lang="scss" scoped>
.tag-admin {
  display: flex;
  height: 100%;
  color: #333;
  border-top: 1px solid #ddd;

  .search-box {
    display: flex;
    margin: 10px 0;

    .el-select {
      /deep/ .el-input__inner {
        border-radius: 4px 0 0 4px;
      }
    }

    .el-button {
      border-radius: 0 4px 4px 0;
    }
  }

  .modules {
    display: flex;
    flex: 400px 0 0;
    padding: 10px;
    flex-direction: column;
    border-right: 1px solid #ddd;

    .module-list {
      flex: 1;

      &_item {
        display: flex;
        font-size: 16px;
        cursor: pointer;
        padding: 0 16px;
        height: 40px;
        line-height: 40px;
        margin-bottom: 2px;
        transition: all 0.3s;
        align-items: center;
        .label {
          max-width: 200px;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }

        &:hover {
          background-color: #eee;

          .count {
            opacity: 1;
          }
        }

        &.active {
          color: #00b8e6;
          font-weight: bold;
          background-color: rgba($color: #0000ff, $alpha: 0.05);
        }
      }
    }
  }

  .tags {
    flex: 1;
    display: flex;
    padding: 20px;
    flex-direction: column;

    .add-btn {
      display: flex;
      height: 32px;
      margin: 10px 0;
      border-radius: 2px;
      align-items: center;
      cursor: pointer;
      color: #999;
      justify-content: center;
      border: 1px dashed #ddd;

      &:hover {
        color: #666;
        border-color: #ccc;
      }

      .el-icon-plus {
        margin-right: 6px;
      }
    }

    .el-tree {
      // padding: 10px;
      /deep/ .el-tree-node {
        &.is-current.is-focusable {
          background-color: rgba($color: #0000ff, $alpha: 0.05);
        }

        .el-tree-node__content {
          height: 36px;
        }
      }
    }

    .custom-tree-node {
      flex: 1;

      .tag-name {
        padding-right: 20px;

        &:hover {
          .count {
            opacity: 1;
          }

          .icons {
            display: inline-block;
          }
        }
      }

      .icons {
        float: right;
        display: none;
        font-size: 16px;

        i {
          cursor: pointer;

          &:hover {
            color: #00b8e6;
          }

          &.el-icon-delete {
            margin-left: 6px;
          }
        }
      }
    }
  }

  .count {
    display: inline-flex;
    opacity: 0;
    font-size: 12px;
    color: #666;
    margin-left: 30px;
    align-items: center;
    vertical-align: middle;

    &::before {
      content: '';
      width: 4px;
      height: 4px;
      margin-right: 6px;
      border-radius: 50%;
      background-color: #666;
    }
  }

  .tag-detail {
    position: relative;
    flex: 300px 0 0;
    padding: 20px;
    border-left: 1px solid #ddd;

    .tag-name {
      font-size: 16px;
      font-weight: bold;
      margin: 10px 0 20px;
      text-align: center;
    }

    .el-form-item {
      margin-bottom: 10px;
    }

    .el-icon-close {
      position: absolute;
      top: 10px;
      right: 10px;
      font-size: 16px;
      cursor: pointer;

      &:hover {
        color: #000;
      }
    }
  }
}
</style>
<style lang="scss">

.el-autocomplete-suggestion.search-popper {
  &[x-placement^='bottom'] {
    margin-top: 6px;
  }

  li {
    margin-bottom: 12px;
    line-height: normal;

    &:last-of-type {
      margin-bottom: 0;
    }
  }

  .title {
    font-size: 16px;
    color: rgba(53, 65, 84, 1);
  }

  .content {
    font-size: 14px;
    color: rgba(53, 65, 84, 0.7);
  }

  .strong {
    color: #1fc880;
  }
}

.el-popper {
  &.search-popper {
    .search-results {
      .module-name {
        color: #000;
        font-weight: bold;
        font-size: 16px;
        line-height: 40px;
      }

      .tag-list {
        line-height: 36px;

        .tag-list_item {
          cursor: pointer;
          padding-left: 16px;
          margin-bottom: 2px;

          &:hover {
            background-color: rgba($color: #0000ff, $alpha: 0.05);
          }

          .mark {
            color: #00b8e6;
          }
        }
      }
    }
  }
}
</style>
